home *** CD-ROM | disk | FTP | other *** search
- /********************************************************************
- FLOATING WINDOWS 1.3
- Copyright 1990 Patrick Doane. All Rights Reserved
- ********************************************************************/
-
- #include "Floating.h"
-
- WindowPtr bottomFloat,topFloat,topWindow;
- RgnHandle drawRgn,windowRgn,dragRgn;
- GrafPtr wPort;
- Rect dragRect;
-
- void InitFloat(void)
- {
- /* Initialize all of the internal variables */
- drawRgn = NewRgn();
- windowRgn = NewRgn();
- dragRgn = NewRgn();
-
- wPort = (GrafPtr)NewPtrClear(sizeof(GrafPort));
- OpenPort(wPort);
-
- topFloat = 0L;
- bottomFloat = 0L;
- topWindow = 0L;
-
- dragRect = (**GetGrayRgn()).rgnBBox;
- InsetRect(&dragRect,4,4);
- }
-
- void UpdateTopWindow(void)
- {
- if (bottomFloat)
- topWindow = (WindowPtr)((WindowPeek)bottomFloat)->nextWindow;
- else
- topWindow = FrontWindow();
- }
-
- void UpdateFloats(void)
- {
- WindowPeek theWindow;
-
- topFloat = 0L; /* Clear variables */
- bottomFloat = 0L;
- theWindow = (WindowPeek)FrontWindow(); /* Start with the front window */
- if (IsFloating((WindowPtr)theWindow)) /* Is it a floating window? */
- { topFloat = (WindowPtr)theWindow; /* Yep, let's start figuring
- out our list starting with
- that one */
-
- while (IsFloating((WindowPtr)theWindow))
- { /* Continue updating our bottom pointer until we have found the
- the last window */
- bottomFloat = (WindowPtr)theWindow;
- theWindow = theWindow->nextWindow;
- if (!theWindow)
- break;
- }
- }
- }
-
- WindowPtr NewFloatingWindow(short ResID,Ptr wStorage)
- {
- WindowPtr theWindow;
-
- /* Bring it into existance */
- theWindow = GetNewWindow(ResID,wStorage,0L);
-
- BringToFront(theWindow); /* Floating window must be in front */
- ShowHide(theWindow,true); /* Make sure it is visible */
- if (!topFloat) /* If topFloat is 0L then this is the
- the first floating window to be
- made. Since it is the first, it must
- also be the last */
- bottomFloat = theWindow;
-
- topFloat = theWindow; /* Mark it is as the top floating window */
-
- MakeFloating(theWindow); /* And mark it as a floating window */
-
- return theWindow; /* Return reference to theWindow */
- }
-
- void MakeFloating(WindowPtr whichWindow)
- {
- /* Mark it as a floating window */
- ((WindowPeek)whichWindow)->windowKind = 317;
- BringToFront(whichWindow); /* Floating window must be in front */
- }
-
- Boolean IsFloating(WindowPtr whichWindow)
- {
- /* Is it a floating window? */
- return (((WindowPeek)whichWindow)->windowKind == 317);
- }
-
- void CloseTheWindow(WindowPtr whichWindow)
- {
- register WindowPeek theWindow;
-
- CloseWindow(whichWindow);
-
- /* Calculate the next window to hilite. Start with the next window
- behind the one you are closing. Continue until you find the first
- visable one. */
-
- theWindow = ((WindowPeek)whichWindow)->nextWindow;
- if (theWindow)
- { while (!theWindow->visible)
- { theWindow = theWindow->nextWindow;
- if (!theWindow)
- break;
- }
- }
-
- /* If we got a window (other than 0L) then Hilite it and tell the
- toolbox to activate that window */
- if (theWindow)
- { HiliteWindow(theWindow,true);
- CurActivate = (WindowPtr)theWindow;
- /* Since one of the windows that was killed could have been a floating
- window. We rebuild that list starting with the frontmost window
- and working the way through the list until we find the first
- nonfloating window which marks the end of the floats. */
-
- UpdateFloats();
- }
- else /* We have no windows left so hide our floats */
- HideFloats();
- UpdateTopWindow();
- }
-
- void DisposeTheWindow(WindowPtr whichWindow)
- {
- register WindowPeek theWindow;
-
- DisposeWindow(whichWindow);
-
- /* Calculate the next window to hilite. Start with the next window
- behind the one you are closing. Continue until you find the first
- visable one. */
-
- theWindow = ((WindowPeek)whichWindow)->nextWindow;
- if (theWindow)
- { while (!theWindow->visible)
- { theWindow = theWindow->nextWindow;
- if (!theWindow)
- break;
- }
- }
-
- /* If we got a window (other than 0L) then Hilite it and tell the
- toolbox to activate that window */
- if (theWindow)
- { HiliteWindow((WindowPtr)theWindow,true);
- CurActivate = (WindowPtr)theWindow;
- /* Since one of the windows that was killed could have been a floating
- window. We rebuild that list starting with the frontmost window
- and working the way through the list until we find the first
- nonfloating window which marks the end of the floats. */
-
- UpdateFloats();
- }
- else /* We have no windows left so hide our floats */
- HideFloats();
- UpdateTopWindow();
- }
-
- void ShowTheWindow(WindowPtr whichWindow)
- {
- ShowWindow(whichWindow); /* Call Toolbox Procedure */
-
- if (whichWindow == (WindowPtr)((WindowPeek)bottomFloat)->nextWindow)
- /* If the window is now the
- top nonfloating window,
- Hilite it */
- HiliteWindow(whichWindow,true);
- UpdateFloats();
- }
-
- void HideTheWindow(WindowPtr whichWindow)
- {
- register WindowPeek theWindow;
-
- HideWindow(whichWindow); /* Call Toolbox procedure */
-
- /* Start with the next window behind the one we are hiding.
- Continue searching until we find a visible one. */
-
- theWindow = ((WindowPeek)whichWindow)->nextWindow;
- while (!theWindow->visible)
- { theWindow = theWindow->nextWindow;
- if (!theWindow)
- break;
- }
-
- if (theWindow) /* If we found a window, Hilite it */
- HiliteWindow(theWindow,true);
- UpdateFloats();
- }
-
- void ShowFloats(void)
- {
- register WindowPeek theWindow;
-
- if (topFloat) /* Do we have floating windows? */
- { theWindow = (WindowPeek)topFloat; /* Start with the top one */
-
- while (theWindow != ((WindowPeek)bottomFloat)->nextWindow)
- /* Contine until we reach the
- last floating window */
-
- { /* Show the window and move
- on to the next */
- ShowHide((WindowPtr)theWindow,true);
- theWindow = theWindow->nextWindow;
- if (!theWindow)
- break;
- }
- }
- }
-
- void HideFloats(void)
- {
- register WindowPeek theWindow;
-
- if (topFloat) /* Do we have floating windows? */
- { theWindow = (WindowPeek)topFloat; /* Start with the top one */
-
- while (theWindow != ((WindowPeek)bottomFloat)->nextWindow)
- /* Contine until we reach the
- last floating window */
-
- { /* Hide the window and move
- on to the next */
- ShowHide((WindowPtr)theWindow,false);
- theWindow = theWindow->nextWindow;
- if (!theWindow)
- break;
- }
- }
- }
-
- WindowPtr CurrentWindow(void)
- {
- return topWindow; /* Just return our variable */
- }
-
- void SelectTheWindow(register WindowPtr whichWindow)
- {
- Boolean floating; /* Is it a floating window */
- register WindowPeek bottomPeek; /* Reference to bottom float */
- register WindowPeek theWindowPeek; /* Generic reference to window */
- WindowPtr lastTop; /* The last top window */
- register WindowPeek beforePeek; /* The location of where the
- the window will be moved */
- GrafPtr savePort;
-
- floating = IsFloating(whichWindow); /* Is it a floating window? */
-
- if (floating)
- { if (whichWindow != topFloat)
- { /* If it is not the front floating window, bring it to the front */
- BringToFront(whichWindow);
- topFloat = whichWindow;
-
- /* and find the last floating window */
- theWindowPeek = (WindowPeek)whichWindow;
- while (IsFloating((WindowPtr)theWindowPeek))
- { bottomFloat = (WindowPtr)theWindowPeek;
- theWindowPeek = theWindowPeek->nextWindow;
- }
- }
- }
- else
- { if (!bottomFloat) /* if there are no other floating windows
- just bring it to the front. */
- { if (whichWindow != FrontWindow())
- SelectWindow(whichWindow);
- }
- else
- { bottomPeek = (WindowPeek)bottomFloat;
- theWindowPeek = (WindowPeek)whichWindow;
-
- if (theWindowPeek != bottomPeek->nextWindow)
- { /* It's not the top document window, now we find what
- that is */
- lastTop = (WindowPtr)bottomPeek->nextWindow;
-
- /* Create deactivate event for last active document window */
- CurDeactive = lastTop;
- HiliteWindow(lastTop,false);
-
- /* Now we rewrite the window list to change the location
- of the window. First we find the window that was before
- the window we want to move. We then set its nextWindow
- field to the window in front of the window we are moving.
- That then removes the window from the window list.
- Now we want to place it rigth after the bottommost
- floating window. To do that, we set the nextWindow
- field of the window we are moving to the window right
- after the bottommost floating window and set the nextWindow
- field of the bottommost floating window to the window
- we are moving. Confusing eh? */
-
- beforePeek = bottomPeek->nextWindow;
- while (beforePeek->nextWindow != theWindowPeek)
- beforePeek = beforePeek->nextWindow;
- beforePeek->nextWindow = theWindowPeek->nextWindow;
-
- theWindowPeek->nextWindow = bottomPeek->nextWindow;
- bottomPeek->nextWindow = theWindowPeek;
-
- /* Now we have to recalculate all the visible regions
- and redraw newly exposed areas */
-
- GetPort(&savePort);
- SetPort(whichWindow);
-
- /* We start with the visible region of our window but
- unfortunately, it is in local coordinates of the
- window so we convert it to global by using the GlobalRgn
- procedure */
-
- CopyRgn(whichWindow->visRgn,drawRgn);
- GlobalRgn(drawRgn);
-
- /* We then subtract the visible region of the window
- from the windows structure region. This gives us
- the area which is being brought to the front */
-
- DiffRgn(theWindowPeek->strucRgn,drawRgn,drawRgn);
-
- /* Paint the area and hilite it to show it is now active */
- PaintOne(whichWindow,drawRgn);
- HiliteWindow(whichWindow,true);
-
- /* PaintOne sets thePort to the Window Manager Port so
- we must reset thePort to whichWindow. We then call
- CalcWindowVis which will recalculate all the visible
- regions */
-
- SetPort(whichWindow);
- CalcWindowVis(theWindowPeek);
-
- /* Then invalidate the region so that it will update
- properly */
-
- InvalRgn(drawRgn);
- SetPort(savePort);
-
- /* And finally, generate another event to activate the
- new window */
-
- CurActivate = whichWindow;
- }
- }
- }
- if (!((WindowPeek)whichWindow)->visible) /* A little kludge
- has been added for floating window support
- which makes sure to make the window visible
- if it is hidden */
- ShowHide(whichWindow,true);
-
- UpdateTopWindow(); /* Rebuild our window list */
- }
-
- void DragTheWindow(WindowPtr whichWindow,EventRecord *theEvent)
- {
- GrafPtr savePort; /* Saved graphics pointer */
- Point thePoint; /* Used to remember the original
- location of the window */
- long newLoc; /* Window's new position */
- short hDelta,vDelta; /* How much to move the window */
- register WindowPeek theWindow;
-
- /* Since dragging a window automatically brings it to the front
- unless you are holding the command key down, this routine needs
- to be redone. Otherwise it would kill the floating window
- relationship */
-
- /* If it's a floating window and not the front floating window
- and the command key is not down, bring it to the front before
- draggin */
- if (IsFloating(whichWindow))
- { if (whichWindow != topFloat && !(theEvent->modifiers & cmdKey))
- SelectTheWindow(whichWindow);
- }
- /* if the window is not the front document window and the command
- key is not down, select the window and exit */
-
- else if (!topFloat)
- { if (whichWindow != FrontWindow() && !(theEvent->modifiers & cmdKey))
- { SelectWindow(whichWindow);
- return;
- }
- }
- else if (whichWindow != (WindowPtr)((WindowPeek)bottomFloat)->nextWindow
- && !(theEvent->modifiers & cmdKey))
- { SelectTheWindow(whichWindow);
- return;
- }
-
- if (!StillDown())
- return;
-
- GetPort(&savePort);
- SetPort(whichWindow);
-
- /* remember the top-left coordinate of the window */
- thePoint = topLeft(whichWindow->portRect);
- LocalToGlobal(&thePoint);
-
-
- /* Copy the window's structure region to be used for dragging */
- CopyRgn(((WindowPeek)whichWindow)->strucRgn,dragRgn);
-
- /* Use our graphics port */
- SetPort(wPort);
-
- /* We must figure out the drag region for the window.
- Start with the top window and work or way through the window
- list altering our graphics port to the screen's visible region.
- This effectively gives us a visible region of the screen minus
- that of all windows above the window we are dragging */
-
- CopyRgn(GetGrayRgn(),wPort->visRgn);
-
- theWindow = (WindowPeek)FrontWindow();
- if (theWindow != (WindowPeek)whichWindow)
- { DiffRgn(wPort->visRgn,theWindow->strucRgn,wPort->visRgn);
- while (theWindow != (WindowPeek)whichWindow)
- { DiffRgn(wPort->visRgn,theWindow->strucRgn,wPort->visRgn);
- theWindow = theWindow->nextWindow;
- }
- }
-
- /* drag the window */
- newLoc = DragGrayRgn(dragRgn,theEvent->where,&dragRect,&dragRect,
- noConstraint,0L);
- if (newLoc != 0x80008000)
- { hDelta = LoWord(newLoc);
- vDelta = HiWord(newLoc);
-
- /* If the window moved, move it */
- if (hDelta || vDelta)
- MoveWindow(whichWindow,hDelta+thePoint.h,vDelta+thePoint.v,false);
- }
- SetPort(savePort);
- }
-
- void CalcWindowVis(register WindowPeek whichWindow)
- {
- register WindowPeek theWindow;
- GrafPtr savePort;
-
- GetPort(&savePort);
-
- /* First we start with an empty region. From there we begin with
- the front window which would be one of the floating windows
- and add its structure region to windowRgn. We continue to add
- in the regions until we reach whichWindow */
-
- SetEmptyRgn(windowRgn);
- theWindow = (WindowPeek)FrontWindow();
- while (theWindow != whichWindow)
- { UnionRgn(windowRgn,theWindow->strucRgn,windowRgn);
- theWindow = theWindow->nextWindow;
- }
-
- /* We now have all the regions of all the windows in front of
- whichWindow. To calculate the visible region of whichWindow,
- we copy its content region (which is in global coordinates) into
- the visRgn field. We then SUBTRACT the region we generated before
- from the visible region of the window. Finally, convert it into
- local coordinates for the toolbox */
-
- SetPort(whichWindow);
- CopyRgn(whichWindow->contRgn,whichWindow->port.visRgn);
- DiffRgn(whichWindow->port.visRgn,windowRgn,whichWindow->port.visRgn);
- LocalRgn(whichWindow->port.visRgn);
-
- /* Now we have to calculate all the visible regions for all windows
- behind whichWindow. We just go through the same process again
- and again, but each time we add the window's structure region
- into windowRgn to subtract again. */
-
- theWindow = whichWindow;
- while (theWindow->nextWindow)
- { UnionRgn(windowRgn,theWindow->strucRgn,windowRgn);
-
- theWindow = theWindow->nextWindow;
-
- SetPort(theWindow);
- CopyRgn(theWindow->contRgn,theWindow->port.visRgn);
- DiffRgn(theWindow->port.visRgn,windowRgn,theWindow->port.visRgn);
- LocalRgn(theWindow->port.visRgn);
- }
- SetPort(savePort);
- }
-
- void GlobalRgn(register RgnHandle changeRgn)
- {
- register Rect theRect;
-
- /* Converts a region into Global Coordinates */
-
- theRect = thePort->portBits.bounds;
- OffsetRgn(changeRgn,-theRect.left,-theRect.top);
- }
-
- void LocalRgn(register RgnHandle changeRgn)
- {
- register Rect theRect;
-
- /* Converts a region into Global Coordinates */
-
- theRect = thePort->portBits.bounds;
- OffsetRgn(changeRgn,theRect.left,theRect.top);
- }